/*
 * jQuery UI Checkbox 0.1
 *
 * Copyright (c) 2009 Jeremy Lea <reg@openpave.org>
 * Dual licensed under the MIT and GPL licenses.
 *
 * http://docs.jquery.com/Licensing
 *
 * Based loosely on plugin by alexander.farkas.
 * http://www.protofunc.com/scripts/jquery/checkbox-radiobutton/
 */


 /*
  *Modified by YuxinYang <yannicyang@gmail.com>
  *
  *Now Support JQuery UI 1.8.x!
  *
  *Enjoy!
  */

        (function ($) {

            // Set up IE for VML if we have not done so already...
            if ($.browser.msie) {
                // IE6 background flicker fix
                try {
                    document.execCommand('BackgroundImageCache', false, true);
                } catch (e) { }

                if (!document.namespaces["v"]) {
                    $("head").prepend("<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />");
                    $("head").prepend("<?import namespace='v' implementation='#default#VML' ?>");
                }
            }

            $.widget("ui.checkbox", {
                _create: function () {
                    // XXX: UI widget will not actually fail...
                    if (!this.element.is(":radio,:checkbox")) {
                        return false;
                    }
                    // _radio stores the members of the radio group (if there is one).
                    if (this.element.is(":radio")) {
                        this._radio = $(this.element[0].form).find("input:radio")
				.filter('[name="' + this.element[0].name + '"]');
                    } else {
                        this._radio = false;
                    }

                    var self = this, o = this.options; // closures for callbacks.
                    // Set the ARIA properties on the native input
                    this.element
			.attr({
			    role: (this._radio ? "radio" : "checkbox"),
			    "aria-checked": !!this.element[0].checked
			});
                    // Create the main wrapper element (which gives the background box)
                    this._wrapper = this.element.wrap($("<span />")).parent()
			.addClass((this._radio ? "ui-radio" : "ui-checkbox") +
				" ui-state-default");
                    // Create the icon element
                    this._wrapper.prepend($("<span/>")
			.addClass("ui-icon " + this._icon(false))
			.click(function (event) {
			    // The icon covers the entire box, but is not in a bubbling
			    // path, so use it to trigger the native event, and let it
			    // take care of the rest.  Gobble up this fake event.
			    self.element[0].click();
			    event.preventDefault();
			    event.stopImmediatePropagation();
			    return false;
			}));
                    if ($.browser.msie) {
                        // IE does not support rounded corners...  We should check
                        // something to see if it does.   But anyway, we make another
                        // element which is a VML roundrect, and hide the normal wrapper.
                        //
                        // XXX: Check if we can use this in place of the span.
                        // XXX: Implement background images.
                        // XXX: Tidy this up to be more jQuery'ish
                        //
                        // Play tricks to get around arcsize bugs...
                        this._wrapper[0].insertAdjacentHTML("afterBegin",
				"<v:roundrect arcsize='" + (this._radio ? "1" : "0.1") +
				"'><v:stroke /><v:fill /></v:roundrect>");
                        this._vml = this._wrapper[0].childNodes[0];
                        var ss = this._wrapper[0].currentStyle;
                        this._vml.style.top = "-1px";
                        this._vml.style.left = "-1px";

                        if (isNaN(parseInt(ss.width))) {
                            this._vml.style.width = "12px"
                        } else {
                            this._vml.style.width = parseInt(ss.width) + 1 + "px";
                        }

                        if (isNaN(parseInt(ss.height))) {
                            this._vml.style.height = "12px"
                        } else {
                            this._vml.style.height = parseInt(ss.height) + 1 + "px";
                        }

                        this._doVML();
                        this._vml.style.visibility = "visible";
                        this._wrapper.css('visibility', 'hidden');
                        // Listen for class or other changes to recreate the elements.
                        this._wrapper[0].onpropertychange = function () {
                            switch (event.propertyName) {
                                case 'className':
                                case 'style.borderTopWidth':
                                case 'style.borderTopColor':
                                case 'style.backgroundColor':
                                case 'style.filter':
                                    self._doVML();
                                    break;
                            }
                        }
                        // Listen for the custom event from the theme switcher.
                        $().bind('ui-theme-switch', function () {
                            setTimeout(function () {
                                self._doVML();
                            }, 500);
                            return false;
                        });
                    }
                    if ($.browser.opera) {
                        // Opera also does not support rounded corners...  Use an SVG
                        // element instead.  Same as above, but a little simpler.
                        //
                        // XXX: Check if we can use this in place of the span.
                        // XXX: Implement background images.
                        // XXX: Tidy this up to be more jQuery'ish
                        var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
                        var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
                        var ss = this._wrapper[0].currentStyle;
                        rect.setAttributeNS(null, "x", "1px");
                        rect.setAttributeNS(null, "y", "1px");
                        rect.setAttributeNS(null, "width", ss.width);
                        rect.setAttributeNS(null, "height", ss.height);
                        rect.setAttributeNS(null, "rx", (this._radio ? "6px" : "2px"));
                        svg.appendChild(rect);
                        this._wrapper.prepend(svg);
                        this._svg = this._wrapper[0].firstChild;
                        this._svg.style.width = parseInt(ss.width) + 2 + "px";
                        this._svg.style.height = parseInt(ss.height) + 2 + "px";
                        this._doSVG();
                        this._svg.style.visibility = "visible";
                        this._wrapper.css('visibility', 'hidden');
                        // Listen for class changes.
                        this._wrapper.bind("DOMAttrModified", function (event) {
                            if (event.attrName === 'class') {
                                self._doSVG();
                            }
                        });
                        // Listen for the custom event from the theme switcher.
                        $().bind("ui-theme-switch", function () {
                            self._doSVG();
                            return false;
                        });
                    }

                    // Set up events...
                    this._wrapper
			.hover(function (event) {
			    if (!o.disabled) {
			        $(this).addClass("ui-state-hover");
			    }
			}, function (event) {
			    if (!o.disabled) {
			        $(this).removeClass("ui-state-hover");
			    }
			})
			.bind("mousedown", function (event) {
			    if (!o.disabled) {
			        $(this).addClass("ui-state-active");
			    }
			})
			.bind("mouseup", function (event) {
			    if (!o.disabled) {
			        $(this).removeClass("ui-state-active");
			    }
			})
			.bind(this.widgetEventPrefix + "focus", function (event) {
			    if (!o.disabled) {
			        if (self._radio) {
			            self._radio.not(self.element)
							.removeClass("ui-state-focus");
			        }
			        $(this).addClass("ui-state-focus");
			    }
			})
			.bind(this.widgetEventPrefix + "blur", function (event) {
			    if (!o.disabled) {
			        $(this).removeClass("ui-state-focus");
			    }
			})
			.bind(this.widgetEventPrefix + "click", function (event) {
			    if (!o.disabled) {
			        if (self._radio) {
			            self._radio.not(self.element).checkbox("uncheck");
			            self.check();
			        } else {
			            self.toggle();
			        }
			    }
			});
                    this.element
			.bind("focus." + this.widgetName, function (event) {
			    self._trigger("focus", event); // Actually checkboxfocus
			})
			.bind("blur." + this.widgetName, function (event) {
			    self._trigger("blur", event); // Actually checkboxblur
			})
			.bind("click." + this.widgetName, function (event) {
			    self._trigger("click", event); // Actually checkboxclick
			});

                    // Capture the initial value
                    this._setOption("checked", !!this.element[0].checked);


                },
                destroy: function () {
                    this._wrapper.replaceWith(this.element);
                    this.element.removeAttr("role")
			.removeAttr("aria-checked")
			.unbind("." + this.widgetName);

                    $.widget.prototype.destroy.apply(this, arguments);
                },

                // Most of the work is done here.
                _setOption: function (key, value) {
                    $.Widget.prototype._setOption.apply(this, arguments);

                    if (key == "disabled") {
                        if (value) {
                            this.element.attr("disabled", "disabled");
                            this._wrapper.removeClass("ui-state-focus ui-state-hover ui-state-active");
                        } else {
                            this.element.removeAttr("disabled");
                        }
                        this._wrapper
				[value ? "addClass" : "removeClass"](
					this.widgetName + "-disabled " +
					this.namespace + "-state-disabled");
                    } else if (key == "checked") {
                        this.element[0].checked = !!value;
                        this.element.attr("aria-checked", !!value);
                        this._wrapper.find(".ui-icon")
				.addClass(this._icon(!!value))
				.removeClass(this._icon(!value));
                    }
                },

                check: function () {
                    this._setOption("checked", true);
                },
                uncheck: function () {
                    this._setOption("checked", false);
                },
                toggle: function () {
                    this._setOption("checked", !this.options.checked);
                },

                _icon: function (state) {
                    if (this._radio) {
                        return "ui-icon-"
				+ this.options[state ? "radioChecked" : "radioUnchecked"];
                    } else {
                        return "ui-icon-"
				+ this.options[state ? "checkboxChecked" : "checkboxUnchecked"];
                    }
                },

                _opacityFixed: false,
                _inFixup: false,
                _fixStyle: function (jq, re) {
                    var s = jq.attr("style").replace(re, "");
                    if (s !== "") {
                        jq.attr("style", s);
                    } else {
                        jq.removeAttr("style");
                    }
                },
                // Only called for IE
                _doVML: function () {
                    if (!this._vml || this._inFixup) {
                        return;
                    }

                    this._inFixup = true;
                    var ss, op;
                    if (this._opacityFixed) {
                        this._vml.childNodes[0].opacity = '1';
                        this._vml.childNodes[1].opacity = '1';
                        this._fixStyle(this._wrapper.find(".ui-icon"), /filter[^;]*\;?/i);
                        this._fixStyle(this._wrapper, /filter[^;]*\;?/i);
                        this._opacityFixed = false;
                    }
                    ss = this._wrapper[0].currentStyle;
                    // IE6 needs both of these...
                    this._vml.strokecolor = ss.borderTopColor;
                    this._vml.strokeweight = ss.borderTopWidth;
                    this._vml.fillcolor = ss.backgroundColor;
                    this._vml.childNodes[0].color = ss.borderTopColor;
                    this._vml.childNodes[0].weight = ss.borderTopWidth;
                    this._vml.childNodes[1].color = ss.backgroundColor;
                    if (ss.filter && ss.filter.search(/Alpha/i) !== -1) {
                        op = /(\d+)/.exec(ss.filter);
                        this._wrapper.find(".ui-icon").css("filter", ss.filter);
                        this._vml.childNodes[0].opacity = op[1] / 100;
                        this._vml.childNodes[1].opacity = op[1] / 100;
                        this._wrapper.css("filter", "");
                        this._opacityFixed = true;
                    }
                    this._inFixup = false;
                },
                // Only called for Opera
                _doSVG: function () {
                    if (!this._svg || this._inFixup) {
                        return;
                    }
                    this._inFixup = true;
                    var ss, op;
                    // Opera doesn't carry over opacity from the hidden container...
                    if (this._opacityFixed) {
                        this._fixStyle(this._wrapper.find(".ui-icon"), /opacity[^;]*\;?/i);
                        this._fixStyle(this._wrapper.find("rect"), /opacity[^;]*\;?/i);
                        this._fixStyle(this._wrapper, /opacity[^;]*\;?/i);
                        this._opacityFixed = false;
                    }
                    ss = this._wrapper[0].currentStyle;
                    this._svg.firstChild.style.stroke = ss.borderTopColor;
                    this._svg.firstChild.style.strokeWidth = ss.borderTopWidth;
                    this._svg.firstChild.style.fill = ss.backgroundColor;
                    if (ss.opacity && ss.opacity !== 1) {
                        op = ss.opacity;
                        this._wrapper.find(".ui-icon").css("opacity", op);
                        this._wrapper.find("rect").css("opacity", op);
                        this._wrapper[0].style.opacity = "1";
                        this._opacityFixed = true;
                    }
                    this._inFixup = false;
                }

            });
            $.ui.checkbox.prototype.options = {
                checkboxChecked: 'check',
                checkboxUnchecked: 'empty',
                radioChecked: 'bullet',
                radioUnchecked: 'empty'
            };

        })(jQuery);
